package idgenservice

import (
	"context"
	"fmt"
	"gitee.com/go-mid/infra/xid"
	"gitee.com/go-mid/infra/xlog"
	"gitee.com/go-mid/idgen/idgenservice/generator"
)

var DefaultIdgenService = &IdgenServiceImpl{}

type IdgenServiceImpl struct {
}

//todo 每个实例启动的时候workid应该不一样，此处先都固定一个
var WorkId int64 = 1

func (m *IdgenServiceImpl) initTask(ctx context.Context) {
	InitIdGeneratorMap(ctx)
}
func InitIdGeneratorMap(ctx context.Context) error {
	fun := "initIdGeneratorMap -->"
	for _, v := range []xid.SnowFlakeModeConfig{
		xid.NewSnowFlakeModeConfig("common", "default"),
		xid.NewSnowFlakeModeConfig("user", "default"),
	} {
		idGen, err := xid.CreateSnowFlakeIdGen(ctx, &v, WorkId)
		if err != nil {
			return err
		}
		xlog.Infof(ctx, "%s set snowflake %s in map", fun, v.GetKey())
		generator.GlobalDataCenter.SetIDGenerator(v.GetKey(), idGen)
	}
	return nil
}

type GetIdReq struct {
	Sname     string `json:"sname"`
	Namespace string `json:"namespace"`
}
type GetIdRes struct {
	Id int64 `json:"id"`
}

func (p *IdgenServiceImpl) GetId(ctx context.Context, req *GetIdReq) (*GetIdRes, error) {
	fun := "IdgenServiceImpl.GetId -->"
	key := xid.GetGeneratorKey(req.Sname, req.Namespace)
	idGen, err := generator.GlobalDataCenter.GetIdGenerator(key)
	if err != nil {
		xlog.Warnf(ctx, "%s Get Id Generator error : %v", fun, err)
		return nil, fmt.Errorf("no idgen config: %s", key)
	}
	id, err := idGen.GetId(ctx)
	if err != nil {
		xlog.Warnf(ctx, "%s gen id  error :req: %v, err:  %v", fun, req, err)
		return nil, err
	}
	return &GetIdRes{
		Id: id,
	}, nil
}

type GetTimeReq struct {
	Sname     string `json:"sname"`
	Namespace string `json:"namespace"`
	Id        int64  `json:"id"`
}
type GetTimeRes struct {
	TimestampMs int64 `json:"timestamp_ms"`
	WorkId      int64 `json:"work_id"`
	Sequence    int64 `json:"sequence"`
}

func (p *IdgenServiceImpl) GetTime(ctx context.Context, req *GetTimeReq) (*GetTimeRes, error) {
	fun := "IdgenServiceImpl.GetTime -->"
	key := xid.GetGeneratorKey(req.Sname, req.Namespace)
	idGen, err := generator.GlobalDataCenter.GetIdGenerator(key)
	if err != nil {
		xlog.Warnf(ctx, "%s Get Id Generator error : %v", fun, err)
		return nil, fmt.Errorf("no idgen config: %s", key)
	}
	timeStampMs, workId, sequence := idGen.UnmarshalId(ctx, req.Id)
	return &GetTimeRes{
		TimestampMs: timeStampMs,
		WorkId:      workId,
		Sequence:    sequence,
	}, nil
}
